package light.head.dao.sys;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import light.head.cache.Cache;
import light.head.constant.Parm;
import light.head.constant.Sys;
import light.head.enm.RESULT;
import light.head.framework.base.BaseDAO;
import light.head.framework.entity.PageBean;
import light.head.model.Organ;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Service;

	@Service
	public class OrganOrganDAO extends BaseDAO<Organ, Integer> {

		private final static String sql_loadAll = "FROM Organ o WHERE o.deleted <> 1 AND o.deleted IS NOT NULL";
		private final static String sql_findManagers = "SELECT code FROM UserInfo WHERE oc = ? AND isManager = 1";
		
		public RESULT findByMap(Map<String, String> map, PageBean pb) {
			StringBuffer hql = new StringBuffer("FROM Organ o WHERE 1=1");

			List<Object> parm = null;
			if (null != map) {
				parm = new ArrayList<Object>();
				
				String name = map.get(Parm.NAME);
				String otc = map.get(Parm.OTC);
				String deleted = map.get(Parm.DELETED);
				String parentCode = map.get(Parm.PARENT_CODE);
				String isUsing = map.get(Parm.IS_USING);
				
				if (isNotNull(name)) {
					hql.append(" AND o.name LIKE ?");
					parm.add("%" + name + "%");
				}
				if (isNotNull(otc)) {
					hql.append(" AND o.otc = ?");
					parm.add(Integer.parseInt(otc));
				}
				if (isNotNull(deleted)) {
					hql.append(" AND o.deleted = ?");
					parm.add(Boolean.parseBoolean(deleted));
				}
				if (isNotNull(parentCode)) {
					hql.append(" AND o.pc = ?");
					parm.add(Integer.parseInt(parentCode));
				} else {
					hql.append(" AND o.pc = ?");
					parm.add(Sys.ZERO);
				}
				if(isNotNull(isUsing)){
					hql.append(" AND o.isUsing = ?");
					parm.add(Boolean.parseBoolean(isUsing));
				}
				
				

				/********************** Jian **************************/
				String supplier = map.get(Parm.SUPPLIER);
				String distributor = map.get(Parm.DISTRIBUTOR);
				// 有该参数说明需要将机构关系中指定supplier相关的distributor排除
				if (isNotNull(supplier)) {
					hql.append(" AND o.code <> ? AND o.code NOT IN (SELECT orrn.distributor FROM OrganRelation orrn WHERE orrn.supplier = ? AND orrn.sc = 1)");
					parm.add(getRoot(Integer.parseInt(supplier)).getCode());
					parm.add(Integer.parseInt(supplier));
				}
				// 有该参数说明需要将机构关系中指定distributor相关的supplier排除
				if (isNotNull(distributor)) {
					hql.append(" AND o.code <> ? AND o.code NOT IN (SELECT orrn.supplier FROM OrganRelation orrn WHERE orrn.distributor = ? AND orrn.dc = 1)");
					parm.add(getRoot(Integer.parseInt(distributor)).getCode());
					parm.add(Integer.parseInt(distributor));
				}
				/********************** ******************************/
			}
			hql.append(" ORDER BY o.code");
			return findToPageBean(hql.toString(), pb, parm);
		}
		
		public RESULT update(Organ cbi) {
			if (null == cbi)
				return RESULT.PARAMETER_ERROR;
			
			Organ old = get(cbi.getCode());
			if (null == old)
				return RESULT.NOT_FIND;
			
			if (isNotNull(cbi.getName())) {
				old.setName(cbi.getName());
			}
			if (cbi.getOtc() != null)
				old.setOtc(cbi.getOtc());
			if (null != cbi.getDeleted())
				old.setDeleted(cbi.getDeleted());
			if (isNotNull(cbi.getSite()))
				old.setSite(cbi.getSite());
			if (isNotNull(cbi.getLogo()))
				old.setLogo(cbi.getLogo());
			if (null != cbi.getMc())
				old.setMc(cbi.getMc());
			if (null != cbi.getManager())
				old.setManager(cbi.getManager());
			if (null != cbi.getPc())	// 修改父机构编号
				old.setPc(cbi.getPc());
			if (null != cbi.getIsUsing()) {
				old.setIsUsing(cbi.getIsUsing());
			}
			if ((isNotNull(cbi.getAbbname()) && cbi.getAbbname().equals(old.getAbbname())) || !isNotNull(old.getAbbname())) {
				old.setAbbname(cbi.getAbbname());
			}
			if (RESULT.SUCCESS == upd(old)) {
				this.loadAll();
				return RESULT.SUCCESS;
			} else {
				return RESULT.ERROR;
			}
		}
		
		
		
		
		public Organ getRoot(Integer code) {
			if (null == code)
				return null;
			Organ o = getOrgan(code);
			if (o.getPc() == null || o.getPc() == 0)
				return o;
			else 
				return getRoot(o.getPc());
		}
		
		/**
		 * 根据机构编号在缓存中获取对应的机构
		 * @param	机构编号
		 */
		public Organ getOrgan(Integer code) {
			if (null == Cache.organList || Cache.organList.size() == 0)
				loadAll();
			return aidGetOrgan(code, Cache.organList);
		}
		public Organ aidGetOrgan(Integer code, List<Organ> list) {
			if (null == code || null == list || list.size() == 0)
				return null;
			Organ result = null;
			for (Organ o : list) {
				if (o.getCode().equals(code.intValue())) 
					return o;
				else 
					result = aidGetOrgan(code, o.getSonList());
				if (null != result)
					return result;
			}
			return null;
		}
		
		public List<Organ> getAll() {
			if (null == Cache.organList || Cache.organList.size() == 0)
				loadAll();
			return Cache.organList;
		}
		
		/**
		 * 加载所有机构信息，并保存其父子结构
		 */
		public RESULT loadAll() {
			List<Organ> list = find(sql_loadAll);
			for (Organ o : list) {
				for (Organ so : list) {
					if (o.getCode().intValue() == so.getPc().intValue()) {
						if (null == o.getSonList())
							o.setSonList(new ArrayList<Organ>());
						
						o.getSonList().add(so);
					}
				}
			}
			List<Organ> organList = new ArrayList<Organ>();
			for (Organ o : list) {
				if (null == o.getPc() || 0 >= o.getPc().intValue())
					organList.add(o);
			}
			Cache.organList = organList;
			return RESULT.SUCCESS;
		}
		
		/**
		 * 将指定机构的所有子孙机构编号构建到指定的codes参数中,以逗号分隔
		 * @param	需要构建的父机构编号
		 * @param	保存编号的StringBuffer
		 */
		public void findSubCode(Organ organ, StringBuffer codes) {
			codes.append(organ.getCode() + ",");
			if (null != organ.getSonList() && organ.getSonList().size() > 0)
				for (Organ son : organ.getSonList())
					findSubCode(son, codes);
		}
		
		/**
		 * 将指定机构的所有子孙机构编号构建到指定的codes参数中
		 * @param	机构对象
		 * @param	保存编号参数的列表
		 */
		public void findSubCode(Organ organ, List<Object> codes) {
			if (null == codes)
				codes = new ArrayList<Object>();
			codes.add(organ.getCode());
			if (null != organ.getSonList() && organ.getSonList().size() > 0)
				for (Organ son : organ.getSonList())
					findSubCode(son, codes);
		}
		
		/**
		 * 朱修贤 2013年7月17日 15:03
		 * 查询分销商(渠道,经销商)
		 * @param map
		 * @param pageBean
		 * @return
		 */
		public RESULT findDistByMap(Map<String, String> map, PageBean pageBean) {
			StringBuffer hql = new StringBuffer("FROM Organ o WHERE 1 = 1");

			List<Object> parm = null;
			if (null != map) {
				parm = new ArrayList<Object>();
				
				String name = map.get(Parm.NAME);
				String otc = map.get(Parm.OTC);
				String deleted = map.get(Parm.DELETED);
				String supplier = map.get(Parm.OC);	// 查询当前机构的分销商(渠道,经销商)
				String sda = map.get(Parm.SDA);
				
				if (isNotNull(name)) {
					hql.append(" AND o.name LIKE ?");
					parm.add("%" + name + "%");
				}
				if (isNotNull(otc)) {
					hql.append(" AND o.otc = ?");
					parm.add(Integer.parseInt(otc));
				}
				if (isNotNull(deleted)) {
					hql.append(" AND o.deleted = ?");
					parm.add(Boolean.parseBoolean(deleted));
				}
				if (isNotNull(supplier)) {
					if (isNotNull(sda)) { // 渠道专员只能选择自己负责的机构
						hql.append("AND o.code IN (SELECT o2.distributor FROM OrganRelation o2 WHERE o2.supplier = ? AND o2.dcc = ?)");
						parm.add(Integer.parseInt(supplier));
						parm.add(Integer.parseInt(sda));
					} else {
						hql.append(" AND o.code IN (SELECT o2.distributor FROM OrganRelation o2 WHERE o2.supplier = ?)");
						parm.add(Integer.parseInt(supplier));
					}
				}
			}
			hql.append(" ORDER BY o.code");
			return findToPageBean(hql.toString(), pageBean, parm);
		}
		
		/**
		 * 非渠道部人员查询
		 * @author 朱修贤
		 * @date 2013-8-5
		 * @time 上午10:16:03
		 * @param map
		 * @param pageBean
		 * @return
		 */
		public RESULT findDistByMapSup(Map<String, String> map, PageBean pageBean) {
			StringBuffer hql = new StringBuffer("FROM Organ o WHERE 1 = 1");

			List<Object> parm = null;
			if (null != map) {
				parm = new ArrayList<Object>();
				
				String name = map.get(Parm.NAME);
				String otc = map.get(Parm.OTC);
				String deleted = map.get(Parm.DELETED);
				String parentCode = map.get(Parm.PARENT_CODE);
				String supplier = map.get(Parm.OC);	// 查询当前机构的分销商(渠道,经销商)
				
				if (isNotNull(name)) {
					hql.append(" AND o.name LIKE ?");
					parm.add("%" + name + "%");
				}
				if (isNotNull(otc)) {
					hql.append(" AND o.otc = ?");
					parm.add(Integer.parseInt(otc));
				}
				if (isNotNull(deleted)) {
					hql.append(" AND o.deleted = ?");
					parm.add(Boolean.parseBoolean(deleted));
				}
				if (isNotNull(parentCode)) {
					hql.append(" AND o.pc = ?");
					parm.add(Integer.parseInt(parentCode));
				} else {
					hql.append(" AND o.pc = ?");
					parm.add(Sys.ZERO);
				}
				if (isNotNull(supplier)) {
					hql.append(" AND o.code IN (SELECT o2.distributor FROM OrganRelation o2 WHERE o2.supplier = (select o3.code from Organ o3 where o3.pc = ? and o3.otc = 3))");
					parm.add(Integer.parseInt(supplier));
				}
			}
			hql.append(" ORDER BY o.code");
			return findToPageBean(hql.toString(), pageBean, parm);
		}
		
		/**
		 * 获取当前机构的所有子机构的编号集合(已包当前机构)
		 * @param oc 机构编号
		 */
		public List<Integer> getSonCodeList(Integer oc) {
			if (null == oc) return null;
			List<Integer> list = new ArrayList<Integer>();
			this.getSonCodes(this.getOrgan(oc).getSonList(), oc, list);
			return list;	
		}
		
		/**
		 * 获取 oc 的所有 子机构的编号集合(sonList 必须是已经把父子机构关系都建好的)
		 * @param sonList oc的子机构集合
		 * @param oc 机构编号
		 * @param list 用来存放所有子机构编号的List
		 */
		public void getSonCodes(List<Organ> sonList, Integer oc, List<Integer> list) {
			if (null == oc)
				return;

			list.add(oc);
			if (null == sonList || sonList.size() == 0) {
				return;
			}
			for (Organ o : sonList) {
				this.getSonCodes(o.getSonList(), o.getCode(), list);
			}
		}
		
		/**
		 * 获取 oc 指定机构的所有子机构信息及子子机构信息的一个数组
		 * @param oc 机构编号
		 */
		public List<Organ> getSonsList(Integer oc) {
			if (null == oc) return null;
		
			Organ o = getOrgan(oc);
			if (null == o) return null;
			
			List<Organ> list = new ArrayList<Organ>();
			this.getSons(o.getSonList(), o, list);
			
			return list;	
		}
		
		/**
		 * 把 org 的子机构 sonList 以及所有子子机构信息放到一个数组里(org 必须是已经把父子机构关系都建好的)
		 * @param sonList org 的子机构集合
		 * @param org 父机构信息
		 * @param list 用来存放所有子机构及子子机构的信息
		 */
		public void getSons(List<Organ> sonList, Organ org, List<Organ> list) {
			if (null == org) return;
			
			if (null == sonList) {
				list.add(org);
				return;
			}

			for (Organ o : sonList) {
				this.getSons(o.getSonList(), o, list);
			}
		}
		
		/**
		 * 在缓存中获取机构类型为type指定的机构信息
		 * @param type 机构类型
		 * @param oc 机构编号
		 */
		public Organ getByOrganType(Integer type, Integer oc) {
			
			if (null == type || null == oc) return null;
			return aidGetByOType(type, this.getOrgan(oc));
		}
		private Organ aidGetByOType(Integer type, Organ organ) {

			if (null != type && organ.getSonList() != null) {
				for (Organ o : organ.getSonList()) {
					if (o.getOtc() == type) {
						return o;
					} else {
						Organ temp = this.aidGetByOType(type, o);
						if (null != temp)
							return temp;
					}
				}
			}
			return null;
		}
		
		public RESULT findSubOrganByCode(Map<String, String> map, PageBean pageBean) {
			StringBuffer hql = new StringBuffer("FROM Organ o WHERE 1 = 1 ");
			List<Object> list = null;
			if (map != null) {
				list = new ArrayList<Object>();
				String code = map.get(Parm.CODE);
				String name = map.get(Parm.NAME);
				String deleted = map.get(Parm.DELETED);
				
				if (isNotNull(code)) { // 机构编号不为空
					Organ organ = this.getOrgan(Integer.parseInt(code)); // 获得当前机构
					Integer organTypeCode = organ.getOtc(); // 获得当前机构的类型
					if (organTypeCode == 1 || organTypeCode == 2) { // 如果机构类型是全功能(恒盛)或渠道(雨杭) 
						StringBuffer sb = new StringBuffer("o.code IN (" + code + ", ");
						List<Organ> sonList = organ.getSonList();
						if (sonList != null && sonList.size() > 0) {
							for (Organ o : sonList) {
								sb.append(o.getCode() + ", ");
							}
						}
						sb.deleteCharAt(sb.lastIndexOf(","));
						sb.append(")");
						hql.append("AND " + sb + " ");
					} else if (organTypeCode == 3 || organTypeCode == 4) { // 如果机构类型是子机构(渠道或者卖场)
						hql.append("AND o.code = ? ");
						list.add(Integer.parseInt(code));
					}
				}
				
				if (isNotNull(name)) {
					hql.append("AND o.name LIKE ? ");
					list.add("%" + name + "%");
				}
				
				if (isNotNull(deleted)) {
					hql.append("AND o.deleted = ? ");
					list.add(Boolean.parseBoolean(deleted));
				}
			}
			
			hql.append(" ORDER BY o.code");
			return findToPageBean(hql.toString(), pageBean, list);
		}
		
		
		/**
		 * 把oc机构的所有父级机构的编号放到 codes集合中,(不包含本机构编号oc)
		 * @param oc 当前机构
		 */
		public List<Object> getPCodes(Integer oc) {
			if (null == oc)
				return null;
			Organ o = getOrgan(oc);
			if (null != o) {
				List<Object> codes = new ArrayList<Object>();
				this.aidGetPCodes(o.getPc(), codes);
				return codes;
			}
			return null;
		}
		public void aidGetPCodes(Integer pc, List<Object> codes) {
			Organ o = getOrgan(pc);
			if (null != o) {
				codes.add(o.getCode());
				aidGetPCodes(o.getPc(), codes);
			}
		}
		
		/**
		 * 获取指定机构的所有处理订单的财务人员编号
		 * @param	机构编号
		 */
		public List<Integer> findCfoCodes(Integer code) {
			if (null == code)
				return null;
			
			List<Object> ocs = getPCodes(code);
			if (null == ocs)
				ocs = new ArrayList<Object>();
			ocs.add(code);
			StringBuffer sql = new StringBuffer("SELECT u.code FROM UserInfo u, Organ o WHERE u.oc = o.code AND u.rc = o.dorc AND (u.deleted <> 1 AND u.deleted IS NOT NULL) AND (o.deleted <> 1 AND o.deleted IS NOT NULL) AND o.code IN (");
			int len = ocs.size();
			for (int i = 0; i < len; i ++)
				sql.append("?,");
			sql.deleteCharAt(sql.length() - 1).append(")");
			List<Integer> result = query(sql.toString(), null, null, ocs.toArray());
			return result;
		}
		
		/**
		 * 获取指定机构的所有管理员编号
		 * @param	要获取的机构编号
		 */
		public List<Integer> findManagers(Integer code) {
			if (null == code)
				return null;
			List<Integer> managers = query(sql_findManagers, null, null, code);
			return managers;
		}

		
		public RESULT findByMap2(Map<String, String> map, PageBean pageBean) {
			StringBuffer hql = new StringBuffer("FROM Organ o WHERE o.deleted <> 1 ");
			List<Object> params = null;
			if (map != null) {
				params = new ArrayList<Object>();
				String code = map.get(Parm.CODE);
				String name = map.get(Parm.NAME);
				System.out.println(name);
				String pc = map.get(Parm.PC);
				String phone = map.get(Parm.PHONE);
				String credit = map.get(Parm.CREDIT);
				String email = map.get(Parm.E_MAIL);
				
				if (isNotNull(code)) {
					hql.append("AND o.code = ? ");
					params.add(Integer.parseInt(code));
				}
				if (isNotNull(name)) {
					hql.append("AND o.name = ? ");
					params.add(name);
				}
				if (isNotNull(pc)) {
					hql.append("AND o.pc = ? ");
					params.add(Integer.parseInt(pc));
				}
				if (isNotNull(phone)) {
					hql.append("AND o.phone = ? ");
					params.add(phone);
				}
				if (isNotNull(credit)) {
					hql.append("AND o.credit = ? ");
					params.add(credit);
				}
				if (isNotNull(email)) {
					hql.append("AND o.email = ? ");
					params.add(email);
				}
			}
			hql.append("ORDER BY o.code");
			return findToPageBean(hql.toString(), pageBean, params);
		}
		
		public Organ getByName(final String name) {
			return this.getHibernateTemplate().execute(new HibernateCallback<Organ>() {
				@Override
				public Organ doInHibernate(Session session) throws HibernateException,
						SQLException {
					Query query = session.createQuery("FROM Organ o WHERE o.deleted <> 1 AND o.name = ?");
					query.setParameter(0, name);
					return (Organ)query.uniqueResult();
				}
			});
		}
		
		/**
		 * 检查机构是否在使用
		 * @author YangGuangHe
		 * @Time 2013-11-5 上午11:14:36
		 * @param oc	机构编号
		 * @return	在使用中返回 true， 否则返回 false
		 */
		public Boolean checkIsUsing(Integer oc) {
			if (null == oc)
				return null;
			Organ organ = this.getOrgan(oc);
			if (null != organ) {
				if (null != organ.getIsUsing() && organ.getIsUsing() == true)
					return true;
				else 
					return false;
				
			}
			return null;
		}
		
		
		
		/**
		 * 查询oc 指定机够的供应商，经销商，以及所有根机构的子机构
		 * @author YangGuangHe
		 * @Time 2013-11-28 下午5:29:55
		 * @param pb	分页信息
		 * @param oc	机构 编号
		 * @param map	条件
		 */
		public RESULT findSupAndDisAndRootSon (List<Object> orgCodes, Map<String, String> map, PageBean pb) {
			if (null == orgCodes || orgCodes.size() == 0) return RESULT.ERROR;
			StringBuffer sql = new StringBuffer("SELECT o.code, o.name, o.address, o.manager FROM Organ o WHERE o.code IN (");
			StringBuffer countSql = new StringBuffer("SELECT COUNT(*) FROM Organ o WHERE o.code IN (");
			for (int i = 0; i < orgCodes.size(); i++) {
				sql.append("?,");
				countSql.append("?,");
			}
			sql.deleteCharAt(sql.length() - 1).append(")");
			countSql.deleteCharAt(sql.length() - 1).append(")");
			
			return queryToPageBean(pb, sql.toString(), orgCodes, countSql.toString(), orgCodes);
		}
		
		/**
		 * 获取指定机构
		 * @param code
		 * @return
		 */
		public List<Organ> fillAllByOrganCode(Integer code) {
			Organ root = getRoot(code);
			List<Organ> list = new ArrayList<Organ>();
			fillAllSonOrgan(list, root);
			return list;
		}
		/**
		 * 将指定机构的所有子机构赋予list参数中
		 * @param	保存所有机构的list
		 * @param	源机构（该对象中必须保存完整的机构关系）
		 */
		public void fillAllSonOrgan(List<Organ> list, Organ parent) {
			if (null == list)
				list = new ArrayList<Organ>();
			
			list.add(parent);
			if (null != parent.getSonList()) {
				for (Organ o : parent.getSonList()) {
					fillAllSonOrgan(list, o);
				}
			}
		}
	}

